#include <string.h>

#include "libpbd_data.h"
#include "pbd_pblock.h"
#include "pbd_linux.h"
#include "pbd_type.h"
#include "pbd_error.h"

#define PBD_ARP_HDR_LEN 8

struct pbd_arp_hdr{
	uint16 hd;
	uint16 pt;
	uint8 hdl;
	uint8 ptl;
	uint16 op;
};

int pbd_build_arp(pbd_handle_t *handle, uint16 hd, uint16 pt, uint8 hdl, 
uint8 ptl, uint16 op, uint8 *sha, uint8 *sip, uint8 *tha, uint8 *tip)
{
	pbd_pblock_t *pblock;
	struct pbd_arp_hdr arp_hdr;
	int size = PBD_ARP_HDR_LEN + 2 * hdl + 2 * ptl;

	memset((char *)&arp_hdr, 0, PBD_ARP_HDR_LEN);
	arp_hdr.hd = htons(hd);
	arp_hdr.pt = htons(pt);
	arp_hdr.hdl = hdl;
	arp_hdr.ptl = ptl;
	arp_hdr.op = htons(op);

	// create new packet block
	pblock = pbd_pblock_new(size, PBD_LAYER_2P5, PBD_PBLOCK_ARP, (char *)&arp_hdr, PBD_ARP_HDR_LEN);
	if (!pblock) {
		pbd_print(PBD_LOG_WARNING, PBD_FUN, "New Pblock Fail\n");
		goto out_free;
	}

	if (pbd_pblock_append(pblock, sha, hdl) < 0)
		goto out_free;
	if (pbd_pblock_append(pblock, sip, ptl) < 0)
		goto out_free;
	if (pbd_pblock_append(pblock, tha, hdl) < 0)
		goto out_free;
	if (pbd_pblock_append(pblock, tip, ptl) < 0)
		goto out_free;

	// link new packet block
	if (pbd_pblock_add(&handle->pblock_head, pblock) < 0) {
		pbd_print(PBD_LOG_WARNING, PBD_FUN, "Add New Pblock Fail\n");
		goto out_free;
	}
	return 1;

out_free:
	pbd_pblock_free(pblock);
	return -1;
}


int pbd_auto_build_arp(pbd_handle_t *handle, uint16 op, uint8 *sha, uint8 *sip, uint8 *tha, uint8 *tip)
{
	return pbd_build_arp(handle, 1, 0x0800, 6, 4, op, sha, sip, tha, tip);
}

